package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.*;
import com.sky.exception.AddressBookBusinessException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.OrdersService;
import com.sky.vo.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.function.Consumer;

@Service
public class OrdersServiceImpl implements OrdersService {
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;

    /**
     * 提交订单
     *
     * @param dto
     * @return
     */
    @Override
    public OrderSubmitVO submit(OrdersSubmitDTO dto) {
        // 数据转换
        Orders orders = new Orders();
        BeanUtils.copyProperties(dto, orders);
        // 准备数据
        // 12.1先获取地址簿
        // 12.2注入地址簿的mapper层,获取到地址簿对象
        AddressBook addressBook = addressBookMapper.getById(orders.getAddressBookId());
        // 判断地址簿是否为空，为空则新建一个异常抛出
        if (addressBook == null) {
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        // 15.1 注入UserMapper,获取user对象
        User user = userMapper.getById(BaseContext.getCurrentId());
        // 补充数据
        addData(orders, addressBook, user);
        // 在订单表中添加数据
        ordersMapper.add(orders);
        // 获取订单详情表对象
        // 1.创建订单详情表的实体类对象
        List<OrderDetail> orderDetailList = new ArrayList<>();
        // 2.获取用户购物车对象,注入购物车的mapper层
        List<ShoppingCart> shoppingCartList = shoppingCartMapper.list(ShoppingCart.builder().userId(BaseContext.getCurrentId()).build());
        for (ShoppingCart shoppingCart : shoppingCartList) {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(shoppingCart, orderDetail);
            orderDetail.setOrderId(orders.getId());
            // 存到集合中
            orderDetailList.add(orderDetail);
        }

        // 在订单明细表中添加一条数据
        for (OrderDetail orderDetail : orderDetailList) {
            orderDetailMapper.add(orderDetail);
        }

        // 删除购物车数据
        shoppingCartMapper.deleteById(user.getId());

        // 构建一个OrderSubmitVO
        OrderSubmitVO submitVO = OrderSubmitVO.builder()
                .id(orders.getId())
                .orderNumber(orders.getNumber())
                .orderAmount(orders.getAmount())
                .orderTime(orders.getOrderTime())
                .build();
        return submitVO;
    }

    /**
     * 查询历史订单
     *
     * @param dto
     * @return
     */
    @Override
    public PageResult historyOrders(OrdersPageQueryDTO dto) {
        PageHelper.startPage(dto.getPage(), dto.getPageSize());
        dto.setUserId(BaseContext.getCurrentId());
        Page<OrderVO> page = ordersMapper.ordersPage(dto);
        List<OrderVO> orderVOS = page.getResult();
        for (OrderVO orderVO : orderVOS) {
            List<OrderDetail> orderDetails = orderDetailMapper.findByOrderId(orderVO.getId());
            orderVO.setOrderDetailList(orderDetails);
        }
        PageResult pageResult = new PageResult(page.getTotal(), orderVOS);
        return pageResult;
    }

    /**
     * 查询订单详情
     *
     * @param id
     * @return
     */
    @Override
    public OrderVO oderDetailById(Long id) {
        OrderVO orderVO = ordersMapper.findById(id);
        List<OrderDetail> orderDetails = orderDetailMapper.findByOrderId(id);
        orderVO.setOrderDetailList(orderDetails);
        return orderVO;
    }

    /**
     * 取消订单
     *
     * @param id
     */
    @Override
    public void cancelOrder(Long id) {
        OrderVO orderVO = ordersMapper.findById(id);
        orderVO.setStatus(Orders.CANCELLED);
        ordersMapper.updateOrder(orderVO);
    }

    /**
     * 再来一单
     *
     * @param id
     */
    @Override
    public void repetitionOrder(Long id) {
        List<OrderDetail> orderDetails = orderDetailMapper.findByOrderId(id);
        for (OrderDetail orderDetail : orderDetails) {

            ShoppingCart shoppingCart = new ShoppingCart();
            BeanUtils.copyProperties(orderDetail, shoppingCart);
            shoppingCart.setUserId(BaseContext.getCurrentId());
            shoppingCart.setCreateTime(LocalDateTime.now());

            shoppingCartMapper.add(shoppingCart);
        }
    }

    /**
     * 管理端取消订单
     *
     * @param dto
     */
    @Override
    public void cancelAdminOrder(OrdersCancelDTO dto) {
        OrderVO orderVO = ordersMapper.findById(dto.getId());
        orderVO.setCancelReason(dto.getCancelReason());
        orderVO.setStatus(Orders.CANCELLED);
        ordersMapper.updateOrder(orderVO);
    }

    /**
     * 各个状态的订单数量统计
     *
     * @return
     */
    @Override
    public OrderStatisticsVO statistics() {
        Integer confirmed = ordersMapper.statistics(Orders.CONFIRMED);
        Integer deliveryInProgress = ordersMapper.statistics(Orders.DELIVERY_IN_PROGRESS);
        Integer toBeConfirmed = ordersMapper.statistics(Orders.TO_BE_CONFIRMED);
        OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO(toBeConfirmed, confirmed, deliveryInProgress);
        return orderStatisticsVO;
    }

    /**
     * 客户端订单搜索
     *
     * @param dto
     * @return
     */
    @Override
    public PageResult conditionSearch(OrdersPageQueryDTO dto) {
        PageHelper.startPage(dto.getPage(), dto.getPageSize());
        Page<OrderVO> page = ordersMapper.ordersPage(dto);
        List<OrderVO> orderVOList = page.getResult();
        for (OrderVO orderVO : orderVOList) {
            List<OrderDetail> orderDetails = orderDetailMapper.findByOrderId(orderVO.getId());
            for (OrderDetail orderDetail : orderDetails) {
                String name = orderDetail.getName();
                orderVO.setOrderDishes(name);
            }
            orderVO.setOrderDetailList(orderDetails);

        }
        return new PageResult(page.getTotal(), orderVOList);
    }

    /**
     * 接单
     *
     * @param dto
     */
    @Override
    public void confirmOrder(OrdersConfirmDTO dto) {
        OrderVO orderVO = ordersMapper.findById(dto.getId());
        orderVO.setStatus(Orders.CONFIRMED);
        ordersMapper.updateOrder(orderVO);
    }

    /**
     * 拒单
     *
     * @param dto
     */
    @Override
    public void rejectionOrder(OrdersRejectionDTO dto) {
        OrderVO orderVO = ordersMapper.findById(dto.getId());
        orderVO.setStatus(Orders.CANCELLED);
        orderVO.setRejectionReason(dto.getRejectionReason());
        ordersMapper.updateOrder(orderVO);
    }

    /**
     * 派送订单
     *
     * @param id
     */
    @Override
    public void deliveryOrder(Long id) {
        OrderVO orderVO = ordersMapper.findById(id);
        orderVO.setStatus(Orders.DELIVERY_IN_PROGRESS);
        ordersMapper.updateOrder(orderVO);
    }

    /**
     * 完成订单
     *
     * @param id
     */
    @Override
    public void completeOrder(Long id) {
        OrderVO orderVO = ordersMapper.findById(id);
        orderVO.setStatus(Orders.COMPLETED);
        ordersMapper.updateOrder(orderVO);
    }

    /**
     * 查询销量排名top10
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {
        // 1.把时间日期的数据补全
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);
        // 2.调用ordersMapper层，查询在这个时间段的已完成的订单，关联订单详情表查询菜品名，销售的数量返回一个List<>集合
        // 3.传入日期数据和订单完成的状态，用一个Map集合封装
        Map<String, Object> map = new HashMap<>();
        map.put("beginTime", beginTime);
        map.put("endTime", endTime);
        map.put("status", Orders.COMPLETED);
        // 4.调用mapper层，得到一个集合的返回值
        List<GoodsSalesDTO> goodsSalesDTOList = ordersMapper.top10(map);
        // 5. 创建商品名称和商品销量集合
        List<String> nameList = new ArrayList<>();
        List<String> numberList = new ArrayList<>();
        // 6.遍历出GoodsSalesDTO中的数据，封装到商品名称和商品销量集合中去
        for (GoodsSalesDTO goodsSalesDTO : goodsSalesDTOList) {
            nameList.add(goodsSalesDTO.getName());
            numberList.add(goodsSalesDTO.getNumber().toString());
        }
        String name = StringUtils.join(nameList, ",");
        String number = StringUtils.join(numberList, ",");

        return new SalesTop10ReportVO(name, number);
    }

    /**
     * 营业额统计
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
        // 1.创建日期集合
        List<LocalDate> dateList = new ArrayList<>();
        // 2.创建营业额列表集合
        List<Double> turnoverList = new ArrayList<>();
        // 判断起始日期是否在结束日期之后
        while (!begin.isAfter(end)) {
            // 起始日期不在结束日期之后
            dateList.add(begin);
            begin = begin.plusDays(1);
        }

        // 然后遍历日期集合
        for (LocalDate date : dateList) {
            // 查询今天的营业额
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            // 创建Map集合封装数据
            Map<String, Object> map = new HashMap<>();
            map.put("beginTime", beginTime);
            map.put("endTime", endTime);
            map.put("status", Orders.COMPLETED);
            Double turnover = ordersMapper.turnoverStatistics(map);
            turnoverList.add(turnover);
        }


        return new TurnoverReportVO(StringUtils.join(dateList, ","),
                StringUtils.join(turnoverList, ","));
    }

    /**
     * 订单统计
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
        // 1. 创建日期列表集合
        List<LocalDate> dateList = new ArrayList<>();
        // 2. 创建总订单数列表集合
        List<Integer> orderCountList = new ArrayList<>();
        // 3. 创建有效订单列表集合
        List<Integer> validOrderCountList = new ArrayList<>();
        // 判断起始时间是否是在结束时间之后
        while (!begin.isAfter(end)) {
            dateList.add(begin);
            begin = begin.plusDays(1);
        }
        // 遍历日期集合
        for (LocalDate date : dateList) {
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            // 创建map集合存储数据
            Map<String, Object> map = new HashMap<>();
            map.put("beginTime", beginTime);
            map.put("endTime", endTime);
            // 查询总的订单数
            Integer totalCount = ordersMapper.ordersStatistics(map);
            // 存入总的订单数
            orderCountList.add(totalCount);
            // 查询有效的订单数
            map.put("status", Orders.COMPLETED);
            Integer validCount = ordersMapper.ordersStatistics(map);
            validOrderCountList.add(validCount);
        }
        // 4.需要查询订单总数和有效订单数，定义两个变量，然后遍历两个集合，变量递增
        Integer total = 0;
        for (Integer integer : orderCountList) {
            total += integer;
        }
        Integer valid = 0;
        for (Integer integer : validOrderCountList) {
            valid += integer;
        }
        // 5.需要查询订单完成率，需要有效订单数除以订单总数，且订单总数！= 0
        Double orderCompletionRate = 0.0;
        if (total != 0) {
            orderCompletionRate = valid.doubleValue()/total;
        }
        return new OrderReportVO(StringUtils.join(dateList, ","),
                StringUtils.join(orderCountList, ","),
                StringUtils.join(validOrderCountList, ","),
                total, valid, orderCompletionRate);
    }

    /**
     * 补充数据
     *
     * @param orders
     * @param addressBook
     * @param user
     */
    private void addData(Orders orders, AddressBook addressBook, User user) {
        // 1.id，自增的
        // 2.number 订单号，
        orders.setNumber(UUID.randomUUID().toString().replace("-", ""));
        // 3. status 订单状态
        orders.setStatus(Orders.PENDING_PAYMENT);
        // 4.user_id 下单用户id
        orders.setUserId(BaseContext.getCurrentId());
        // 5.address_book_id 地址id 传入的参数里面有
        // 6.order_time 下单时间
        orders.setOrderTime(LocalDateTime.now());
        // 7.checkout_time 结账时间 需要后续实现
        // 8. payMethod 支付方式 传入的数据
        // 9. payStatus 支付状态
        orders.setPayStatus(Orders.UN_PAID);
        // 10.amount 实收金额 传入的数据
        // 11.remark 备注 传入的数据
        // 12.phone 手机号

        // 12.3 用地址簿对象获取手机号
        orders.setPhone(addressBook.getPhone());
        // 13.address 地址
        // 13.1 用地址簿对象获取地址，把省市区拼接在一起
        String s = addressBook.getProvinceName() + addressBook.getCityName() + addressBook.getCityName();
        // 13.2 再和具体地址一起拼接存入
        orders.setAddress(s + addressBook.getDetail());
        // 14.consignee 收货人
        orders.setConsignee(addressBook.getConsignee());
        // 15.userName 用户名

        // 15.2 根据对象获取用户名存入
        orders.setUserName(user.getName());
        // 16.cancel_reason 订单取消原因 需要后续实现
        // 17.rejection_reason 订单拒绝原因 需要后续实现
        // 18.cancel_time 订单取消时间 需要后续实现
        // 19.estimated_deliver_time 预计送达时间 传入的数据
        // 20.delivery_status 配送状态  传入的数据
        // 21.delivery_time 送达时间    需要后续实现
        // 22.pack_amount 打包费   传入的数据
        // 23.tableware_number 餐具数量 传入的数据
        // 24.tableware_status 餐具数量状态 传入的数据
    }

}
